//  Created by <Omar MALAGOUEN>

//  Copyright 2011 All rights reserved.
//

/*
 * Various utilities for command line tools
 * Copyright (c) 2000-2010 Omar Malagouen
 *
 * This file is part of Kakola.
 *
 * Kakola is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Kakola is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Kakola; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "cvideofile.h"
#include "common.h"

CVideoFile::CVideoFile()
{
    state = notStarted;
    length = 0;
    percentageDone = 0;
    sizeInKO = 0;
    status = -1;
    elapsed = 0;
    takeIntoConsiderationForTimeCalculation = true;

    outputFileVideoBitrate = 700;
    outputFileAudioBitrate = 128;

    alreadyCounted = false;
    askUserForInputMsgDone = false;
    CPU = new int;
    exitCode = -99999;
    durationSeconde = 0;
    sendedToProgressBar = 0;
    numberOfPassAlreadydone = 0;
    newProgressBarCreated = false;
    durationSendedToProgressBar = false;
    dependance = "false";

    this->profile = new CProfile;

    profileComboBox = new QComboBox();
    videoFileListProfileInCombo = new QListWidget;
    elapsed = 0;
    overwrite = "notAssigned";
    changeCmdLine = false;
}

bool CVideoFile::endedSuccessfully()
{
    if ( this->exitStatus == QProcess::NormalExit &&
         ( this->exitCode == 0 ||
           (this->exitCode != 2 && this->profile->program[this->numberOfPassAlreadydone-1].contains("mkvmerge") ) ||
           ( this->profile->program[this->numberOfPassAlreadydone-1].contains("cp") &&
             this->errMsgEnc.contains("chflags") &&
             QFileInfo(this->cleanSrcFilePath).size() == QFileInfo(this->destFileName).size()
             )
           )
         )
        return true;
    return false;
}

CVideoFile::~CVideoFile()
{

    while (videoFileListProfileInCombo->count() != 0)
    {
        delete videoFileListProfileInCombo->takeItem(0);
        videoFileListProfileInCombo->removeItemWidget(videoFileListProfileInCombo->takeItem(0));
    }
    delete this->videoFileListProfileInCombo;
}

bool CVideoFile::setCPU(int i)
{
    QSettings *settings = new QSettings(QSettings::NativeFormat,
                                        QSettings::UserScope,QCoreApplication::organizationName(),
                                        QCoreApplication::applicationName());

    int numberOfCPUToUse = settings->value("numberCPU").toInt();
    if ( i >= numberOfCPUToUse)
        i = 0;

    if (    this->profile->listCommand.at(0)->contains("libx264", Qt::CaseInsensitive)
        ||  this->profile->programContainString("cp"))
        *(this->CPU) = 0;
    else if ( this->dependance != "true" )
        *(this->CPU) = i;
    else
        *(this->CPU) = 0;
    return true;
}

bool CVideoFile::setFileName(){
    this->cleanSrcFilePath = QDir::cleanPath(fileName);
    QFileInfo fi(this->cleanSrcFilePath);
    this->srcFileExtension = fi.suffix();
    this->fileName = fi.fileName();
    this->srcCompleteBaseName = fi.completeBaseName();

    if (QDir(this->cleanSrcFilePath).exists())
        this->srcDirName = this->cleanSrcFilePath;
    else
        this->srcDirName = fi.absolutePath ();


    qDebug("fileNames is = %s",fileName.toLatin1().data());
    if (QFileInfo(cleanSrcFilePath).isDir())
    {
        srcUpDirName = QDir::cleanPath(cleanSrcFilePath + "/../");
    }
    else
        srcUpDirName = srcDirName;


    lastModified = QFileInfo(cleanSrcFilePath).lastModified();
    qDebug("File %s Last modified %s",cleanSrcFilePath.toLatin1().data(),lastModified.toString("yyyyMMddhhmmss").toLatin1().data());
    return true;
}

QString CVideoFile::qSetToString(char sep,int decallage)
{
    QString res;
    foreach(int i, this->dependanceList)
    {
        res = res + QString::number(i+decallage,10) + sep;
    }
    return res;
}

void CVideoFile::stringToQSet(QString str,char sep,int decallage)
{
    this->dependanceList.clear();
    QStringList list = str.split(sep);
    bool b = false;
    foreach(QString l_str,list)
    {
        if (l_str != "")
            this->dependanceList.insert(l_str.toInt(&b,10)+decallage);
    }

}

bool CVideoFile::setDestFileName()
{
    QString path = "/usr/local///bin/toto/.././/myapp.tar.gz";
    QFileInfo fi(path);
    qDebug("PATH=%s",path.toLatin1().data());
    qDebug("** extension = %s",fi.suffix().toLatin1().data());
    qDebug("** fileName = %s",fi.fileName().toLatin1().data());
    qDebug("** baseName = %s",fi.baseName().toLatin1().data());
    qDebug("** completeBaseName = %s",fi.completeBaseName().toLatin1().data());
    qDebug("** filePath = %s",fi.filePath().toLatin1().data());
    path = QDir::cleanPath(path);
    qDebug("** cleanPath = %s",path.toLatin1().data());
    qDebug("\n");

    path = "/usr/local/bin/ls";
    fi = QFileInfo(path);
    qDebug("PATH=%s",path.toLatin1().data());
    qDebug("** extension = %s",fi.suffix().toLatin1().data());
    qDebug("** fileName = %s",fi.fileName().toLatin1().data());
    qDebug("** baseName = %s",fi.baseName().toLatin1().data());
    qDebug("** completeBaseName = %s",fi.completeBaseName().toLatin1().data());
    qDebug("** filePath = %s",fi.filePath().toLatin1().data());
    path = QDir::cleanPath(path);
    qDebug("** cleanPath = %s",path.toLatin1().data());
    qDebug("\n");

    path = "/usr/local/bin/";
    fi = QFileInfo(path);
    qDebug("PATH=%s",path.toLatin1().data());
    qDebug("** extension = %s",fi.suffix().toLatin1().data());
    qDebug("** fileName = %s",fi.fileName().toLatin1().data());
    qDebug("** baseName = %s",fi.baseName().toLatin1().data());
    qDebug("** completeBaseName = %s",fi.completeBaseName().toLatin1().data());
    qDebug("** filePath = %s",fi.filePath().toLatin1().data());
    path = QDir::cleanPath(path);
    qDebug("** cleanPath = %s",path.toLatin1().data());
    qDebug("\n");

    path = "/home/om/.kakola";
    fi = QFileInfo(path);
    qDebug("PATH=%s",path.toLatin1().data());
    qDebug("** extension = %s",fi.suffix().toLatin1().data());
    qDebug("** fileName = %s",fi.fileName().toLatin1().data());
    qDebug("** baseName = %s",fi.baseName().toLatin1().data());
    qDebug("** completeBaseName = %s",fi.completeBaseName().toLatin1().data());
    qDebug("** filePath = %s",fi.filePath().toLatin1().data());
    path = QDir::cleanPath(path);
    qDebug("** cleanPath = %s",path.toLatin1().data());

    return true;
}

QString CVideoFile::basenameToView(){
    QString file;
    if (QFileInfo(this->cleanSrcFilePath).isDir())
        file = QFileInfo(this->cleanSrcFilePath).absoluteFilePath();
    else
        file = this->fileName;

    qDebug("Dir name = %s",file.toLatin1().data());

    if ( file.size() > 60 ){
        return file.left(25) + " ... " + file.right(25);
    }
    return file;
}

void CVideoFile::updatePercentageDone(double f){
    //qDebug("Percentage done for %s = %f",this->filename.toLatin1().data(),f);
    this->percentageDone = f;
}

bool CVideoFile::setBitrate(QString outputFileSize)
{
    outputFileSize.replace("k","",Qt::CaseInsensitive);
    outputFileSize.replace("m","000",Qt::CaseInsensitive);
    outputFileSize.replace("g","000000",Qt::CaseInsensitive);
    qDebug("Out put file size wanted = %s",outputFileSize.toLatin1().data());
    bool ok;
    int outputFileSizeInteger = outputFileSize.toInt(&ok);

    if (outputFileSizeInteger > 800000 && outputFileSizeInteger < 1600000)
        this->outputFileAudioBitrate = 192;
    else if (outputFileSizeInteger > 1600000)
        this->outputFileAudioBitrate = 320;
    else
        this->outputFileAudioBitrate = 128;

    if (this->durationSeconde != 0)
    {
        int A = this->outputFileAudioBitrate;
        int S = outputFileSizeInteger;
        int L = this->durationSeconde;
        this->outputFileVideoBitrate = 8 * ( S - (L*A) / 8 ) / L;
    }
    else
    {
        this->outputFileAudioBitrate = 128;
        this->outputFileVideoBitrate = 800;
    }

    if ( this->outputFileVideoBitrate > 30000)
        this->outputFileVideoBitrate = 30000;
    if ( this->outputFileVideoBitrate < 0)
        this->outputFileVideoBitrate = 800;

    return ok;
}




void CVideoFile::buildCommand(QString ffmpegProg, QString mencoderProg, QString homeDir,
                              QString profileDir, QHash<QString,QString> *hashEventFolderName)
{

    QSettings *settingsProfile = new QSettings(this->profile->dirname + "/" + this->profile->filename,
                                               QSettings::IniFormat,new QObject);

    QString str = settingsProfile->value("createOutputDir").toString();
    qDebug("** Value createOutputDir = %s", str.toLatin1().data());
    if ( (! QDir(this->profile->outputDir).exists())  && settingsProfile->value("createOutputDir").toString() != "0" ){
        QString res = this->profile->outputDir;
        res.replace("~",homeDir + "/");
        QDir thedir(res);
        thedir.mkdir(res);
        qDebug("** Creating output directory %s",res.toLatin1().data());
        this->profile->outputDir = res;
        this->profile->outputDir = QDir::cleanPath(this->profile->outputDir) + "/";
    }


    this->prefix = this->profile->prefix;
    this->suffix = settingsProfile->value("suffix","").toString();
    this->replaceInCmd(&this->suffix);
    this->replaceInCmd(&this->prefix);



    QString myOutPutDir = this->profile->outputDir;
    if (myOutPutDir == "." || myOutPutDir == "./" ){
        myOutPutDir = this->srcDirName;
    }

    lastModified = QFileInfo(this->cleanSrcFilePath).lastModified();

    CDialogEventName *dlgEventName = new CDialogEventName();
    if ( settingsProfile->value("dirEvent") == "onDemand"
         && (*hashEventFolderName)[this->profile->filename] == "" )
    {
        // HERE THE MSG BOX TO ENTER THE EVENT NAME
        QSettings *settings = new QSettings(QSettings::NativeFormat,QSettings::UserScope,QCoreApplication::organizationName(),QCoreApplication::applicationName() );
        QString eventName = settings->value("eventName","New Event").toString();
        dlgEventName->setDefaultEventName(eventName + " " + this->lastModified.toString("yyyyMMdd"));
        dlgEventName->setDir(myOutPutDir);
        dlgEventName->exec();
        this->profile->eventFolderName = dlgEventName->getEventName();
        this->profile->eventFolderName = QDir::cleanPath(this->profile->eventFolderName);
        (*hashEventFolderName)[this->profile->filename] = this->profile->eventFolderName;
        qDebug("Create event %s for profile = %s",
               settingsProfile->value("dirEvent").toString().toLatin1().data(),
               this->profile->filename.toLatin1().data());
    }

    QString *subDirectory = new QString(settingsProfile->value("subdirectory").toString());
    this->replaceInCmd(subDirectory);

    QString outputFullDirectory = myOutPutDir + "/"
                                  + (*hashEventFolderName)[this->profile->filename]
                                  + "/" + *subDirectory + "/" ;
    outputFullDirectory = QDir::cleanPath(outputFullDirectory);
    QDir myDir(outputFullDirectory);


    QString str45 = settingsProfile->value("createOutputDir").toString();
    if ( ! myDir.exists() && str45 != "0"){
        qDebug("** buildCommand Value createOutputDir %s",str45.toLatin1().data());
        qDebug("** buildCommand Create directory event : %s",outputFullDirectory.toLatin1().data());
        myDir.mkpath(outputFullDirectory);
    }
    else
        qDebug("Event dir exist : %s",outputFullDirectory.toLatin1().data());

    QString the_extension = this->profile->extension;

    if (this->profile->extension == "")
        the_extension = srcFileExtension;

    qDebug("the_extension %s",the_extension.toLatin1().data());

    this->dstDirName = outputFullDirectory;

    if (settingsProfile->value("outputFileName","").toString() != "")
    {
        QString *l_outputFileName = new QString(settingsProfile->value("outputFileName","").toString());
        this->replaceInCmd(l_outputFileName);
        this->outputBasename = *l_outputFileName;
        this->destFileName = this->dstDirName + "/" + this->outputBasename;
        // FIXME
        this->destFileSrt = this->dstDirName + "/" + "";
        this->srcFileSrt = this->dstDirName + "/" + "";
    }
    else
    {
        this->outputBasename = this->prefix + this->srcCompleteBaseName +
                               this->suffix + "." + the_extension;
        this->destFileName = this->dstDirName + "/" +this->outputBasename;

        this->destFileSrt = this->dstDirName +"/" +
                            this->prefix + this->srcCompleteBaseName +
                            this->suffix + ".srt";

        this->srcFileSrt = this->srcDirName + "/" + this->srcCompleteBaseName + ".srt";
    }

    qDebug("destFileName %s",destFileName.toLatin1().data());
    qDebug("destFileSrt %s",destFileSrt.toLatin1().data());
    qDebug("srcFileSrt %s",srcFileSrt.toLatin1().data());

    this->listCommand.clear();
    foreach(QString *cmd, this->profile->listCommand){
        qDebug("Command is : %s",cmd->toLatin1().data());

        QString *videoFileCmd = new QString(*cmd);
        qDebug("QString *videoFileCmd =  %s",videoFileCmd->toLatin1().data());
        replaceInCmd(videoFileCmd);
        this->listCommand.append(videoFileCmd);
    }

    this->setCPU(*(this->CPU));
}


void CVideoFile::replaceInCmd(QString *videoFileCmd)
{
    qDebug("CVideoFile::replaceInCmd %s",videoFileCmd->toLatin1().data());
    videoFileCmd->replace("${append}", this->appendToCmdLine);
    videoFileCmd->replace("${input}", this->input);
    videoFileCmd->replace("$year",this->lastModified.toString("yyyy"));
    videoFileCmd->replace("$month",this->lastModified.toString("MM"));
    videoFileCmd->replace("$day",this->lastModified.toString("dd"));
    videoFileCmd->replace("$date",this->lastModified.toString("yyyyMMddhhmmss"));

    QSettings *settings = new QSettings(QSettings::NativeFormat,QSettings::UserScope,QCoreApplication::organizationName(),QCoreApplication::applicationName() );

    QSettings *myProfile = new QSettings(this->profile->dirname + "/" + this->profile->filename,
                                         QSettings::IniFormat,new QObject);
    QString tmpDir = QDir::cleanPath(settings->value("tmpDir","/tmp/").toString());
    QString myOutputFileSize = myProfile->value("outputFileSize","").toString();

    if (myOutputFileSize != "")
    {
        this->setBitrate(myOutputFileSize);
        videoFileCmd->replace("${VIDEOBITRATE}",QString::number(this->outputFileVideoBitrate)+"k");
        videoFileCmd->replace("${AUDIOBITRATE}",QString::number(this->outputFileAudioBitrate)+"k");
    }

    QRegExp reg;

    reg = QRegExp("\\$\\{srcBaseName\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,
                              this->fileName
                              );

    reg = QRegExp("\\$\\{srcfile\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,
                              this->cleanSrcFilePath
                              //+ reg.cap(1)

                              );
    for(int i = 0; i <= 10 ; i++)
    {
        QString str = "program\\[" + QString::number(i,10) + "\\]";
        reg = QRegExp("\\$\\{"+str+"\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,
                              settings->value(this->profile->program[i],this->profile->program[i]).toString()
                              );
    }

    reg = QRegExp("\\$\\{passlogfile\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,
                              tmpDir + "/" + this->fileName + QString(".log")
                              //+ reg.cap(1)

                              );

    reg = QRegExp("\\$\\{dstfile\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,
                              this->destFileName
                              //+ reg.cap(1)
                              );

    reg = QRegExp("\\$\\{destfile\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,
                              this->destFileName
                              //+ reg.cap(1)

                              );

    reg = QRegExp("\\$\\{outputDir\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,""
                              + this->dstDirName
                              //+ reg.cap(1)
                              );

    reg = QRegExp("\\$\\{srcUpDirName\\}");
    if (videoFileCmd->contains(reg))
    {
        videoFileCmd->replace(reg,""
                              + this->srcUpDirName
                              //+ reg.cap(1)
                              + ""
                              );
        qDebug("videoFileCmd %s",videoFileCmd->toLatin1().data());
    }

    reg = QRegExp("\\$\\{srcCompleteBaseName\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,
                              this->srcCompleteBaseName
                              //+ reg.cap(1)
                              );


    QString theExtension = this->profile->extension;
    if (theExtension == "")
        theExtension = this->srcFileExtension;

    reg = QRegExp("\\$\\{outputFileExtension\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,""
                              + theExtension
                              //+ reg.cap(1)+ ""
                              );

    reg = QRegExp("\\$\\{srcUpDirName}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,""
                              + this->srcUpDirName
                              //+ reg.cap(1)+ ""
                              );

    reg = QRegExp("\\$\\{srcdirname\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,""
                              + this->srcDirName
                              //+ reg.cap(1)+ ""
                              );


    reg = QRegExp("\\$\\{outputDirName\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,""
                              + this->dstDirName
                              //+ reg.cap(1)+ ""
                              );

    reg = QRegExp("\\$\\{outputFileName\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,""
                              + this->outputBasename
                              //+ reg.cap(1)+ ""
                              );

    reg = QRegExp("\\$\\{prefix\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,""
                              + this->prefix
                              //+ reg.cap(1)+ ""
                              );

    reg = QRegExp("\\$\\{suffix\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,""
                              + this->suffix
                              //+ reg.cap(1)+ ""
                              );

    reg = QRegExp("\\$\\{tmp\\}");
    if (videoFileCmd->contains(reg))
        videoFileCmd->replace(reg,tmpDir);
}
